/**
 * RLS 中间件
 * 用于在数据库查询前设置当前用户上下文，以便 RLS 策略正确工作
 */

import { pool } from './database'

/**
 * 设置数据库会话中的当前用户ID
 * @param {string|null} userId - 用户ID，null 表示未认证用户
 * @param {Function} callback - 需要在用户上下文中执行的数据库操作
 * @returns {Promise} 操作结果
 */
export async function withUserContext(userId, callback) {
    const client = await pool.connect()

    try {
        // 设置当前用户ID到会话变量
        const userIdValue = userId || ''
        await client.query('SELECT set_config($1, $2, true)', ['app.current_user_id', userIdValue])

        // 在用户上下文中执行回调函数
        const result = await callback(client)

        return result
    } finally {
        // 清理会话变量
        await client.query('SELECT set_config($1, $2, true)', ['app.current_user_id', ''])
        client.release()
    }
}

/**
 * 从请求中提取用户ID的辅助函数
 * 当前实现：由于使用localStorage认证，服务器端无法直接获取用户信息
 * 需要客户端在请求中传递用户ID
 * @param {Request} request - Next.js 请求对象
 * @returns {string|null} 用户ID或null
 */
export function extractUserIdFromRequest(request) {
    try {
        // 方法1: 从 URL 参数中提取（GET 请求）
        const url = new URL(request.url)
        const userIdFromQuery = url.searchParams.get('userId')
        if (userIdFromQuery) {
            return userIdFromQuery
        }

        // 方法2: 从 Authorization header 中提取
        const authHeader = request.headers.get('authorization')
        if (authHeader && authHeader.startsWith('Bearer ')) {
            const token = authHeader.substring(7)
            // 这里可以实现 JWT 解码逻辑
            // const decoded = jwt.verify(token, process.env.JWT_SECRET)
            // return decoded.userId
        }

        // 方法3: 从 cookie 中提取
        const cookies = request.headers.get('cookie')
        if (cookies) {
            const cookieMatch = cookies.match(/auth-token=([^;]+)/)
            if (cookieMatch) {
                const token = cookieMatch[1]
                // 解码 token 获取用户ID
                // const decoded = jwt.verify(token, process.env.JWT_SECRET)
                // return decoded.userId
            }
        }

        // 方法4: 从自定义 header 中提取
        const userIdHeader = request.headers.get('x-user-id')
        if (userIdHeader) {
            return userIdHeader
        }

        return null
    } catch (error) {
        console.error('提取用户ID时出错:', error)
        return null
    }
}

/**
 * RLS 查询包装器
 * 自动处理用户上下文设置的数据库查询函数
 */
export class RLSQuery {
    constructor(userId = null) {
        this.userId = userId
    }

    /**
     * 执行查询
     * @param {string} text - SQL 查询语句
     * @param {Array} params - 查询参数
     * @returns {Promise} 查询结果
     */
    async query(text, params = []) {
        return withUserContext(this.userId, async (client) => {
            return await client.query(text, params)
        })
    }

    /**
     * 执行事务
     * @param {Function} callback - 事务回调函数
     * @returns {Promise} 事务结果
     */
    async transaction(callback) {
        return withUserContext(this.userId, async (client) => {
            try {
                await client.query('BEGIN')
                const result = await callback(client)
                await client.query('COMMIT')
                return result
            } catch (error) {
                await client.query('ROLLBACK')
                throw error
            }
        })
    }
}

/**
 * 创建带有用户上下文的查询实例
 * @param {string|null} userId - 用户ID
 * @returns {RLSQuery} 查询实例
 */
export function createUserQuery(userId) {
    return new RLSQuery(userId)
}

/**
 * API 路由的 RLS 中间件
 * 用于 Next.js API 路由中自动设置用户上下文
 */
export function withRLS(handler) {
    return async (request, context) => {
        // 提取用户ID
        const userId = extractUserIdFromRequest(request)

        // 将用户查询实例添加到请求对象
        request.userQuery = createUserQuery(userId)
        request.userId = userId

        // 调用原始处理器
        return await handler(request, context)
    }
}

/**
 * 验证用户权限的辅助函数
 * @param {string} userId - 当前用户ID
 * @param {string} resourceUserId - 资源所有者ID
 * @param {string} action - 操作类型 (read, write, delete)
 * @returns {boolean} 是否有权限
 */
export function checkPermission(userId, resourceUserId, action = 'read') {
    // 未认证用户只能读取
    if (!userId) {
        return action === 'read'
    }

    // 用户可以对自己的资源执行任何操作
    if (userId === resourceUserId) {
        return true
    }

    // 其他用户只能读取
    return action === 'read'
}

/**
 * 权限检查装饰器
 * @param {string} action - 操作类型
 * @returns {Function} 装饰器函数
 */
export function requirePermission(action) {
    return function (target, propertyKey, descriptor) {
        const originalMethod = descriptor.value

        descriptor.value = async function (...args) {
            const [userId, resourceUserId] = args

            if (!checkPermission(userId, resourceUserId, action)) {
                throw new Error(`权限不足: 无法执行 ${action} 操作`)
            }

            return await originalMethod.apply(this, args)
        }

        return descriptor
    }
}

/**
 * 日志记录函数
 * @param {string} userId - 用户ID
 * @param {string} action - 操作类型
 * @param {string} resource - 资源类型
 * @param {string} resourceId - 资源ID
 * @param {boolean} success - 操作是否成功
 */
export async function logSecurityEvent(userId, action, resource, resourceId, success = true) {
    try {
        const query = createUserQuery(null) // 使用系统权限记录日志

        await query.query(`
            INSERT INTO audit_log (user_id, table_name, operation, record_id, created_at)
            VALUES ($1, $2, $3, $4, NOW())
        `, [userId, resource, action, resourceId])

        if (process.env.NODE_ENV === 'development') {
            console.log(`安全日志: 用户 ${userId || 'anonymous'} ${success ? '成功' : '失败'} ${action} ${resource} ${resourceId}`)
        }
    } catch (error) {
        console.error('记录安全日志失败:', error)
    }
}

export default {
    withUserContext,
    extractUserIdFromRequest,
    RLSQuery,
    createUserQuery,
    withRLS,
    checkPermission,
    requirePermission,
    logSecurityEvent
}